# !/usr/bin/env python

import time
from multiprocessing import Process
from threading import Thread

from pymodbus.client.sync import ModbusTcpClient


class ModbusClient(object):
    """
    modbus通信 连接测试
    """
    _need_write = False
    _need_write_info = {}

    def __init__(self, host='127.0.0.1', port=502, **kwargs):
        self.client = ModbusTcpClient(host=host, port=port)

    def connect(self):
        """网络连接"""
        self.client.connect()

    def __keep_read(self, read_adder, read_length, sleep_time: float = 0.1, unit: int = 1,
                    single_connection: bool = True):
        """
        循环读取数据
        """
        if not single_connection:
            self.connect()
        while True:
            try:
                read_info = self.client.read_holding_registers(read_adder, read_length, unit=unit)
                print(f"read_info :{read_info}")
                print(f"read_info :{read_info.registers}")
            except Exception as e:
                print(f"read error :{e}")

            time.sleep(sleep_time)

    def __keep_write(self, write_adder, write_value: list, sleep_time: float = 0.1, unit: int = 1,
                     single_connection: bool = True):
        """
        循环写入数据
        """
        if not single_connection:
            self.connect()
        while True:
            try:
                write_info = self.client.write_registers(write_adder, write_value, unit=unit)
                print(f"write info :{write_info}")
            except Exception as e:
                print(f"write info :{e}")
            time.sleep(sleep_time)

    def cyclic_read_write(self, read_info: dict, write_info: dict):
        """
        循环读写
        """
        read_adder = read_info.get("read_adder")
        read_length = read_info.get("read_length")
        unit = read_info.get("unit")
        sleep_time = read_info.get("sleep_time")
        write_adder = write_info.get("write_adder")
        write_value = write_info.get("write_value")
        while True:
            try:
                read_info = self.client.read_holding_registers(read_adder, read_length, unit=unit)
                print(f"read_info :{read_info}")
                print(f"read_info :{read_info.registers}")
                if ModbusClient._need_write:
                    if ModbusClient._need_write_info:
                        write_adder = ModbusClient._need_write_info.get("write_adder")
                        write_value = ModbusClient._need_write_info.get("write_value")
                        unit = ModbusClient._need_write_info.get("unit")
                    write_info = self.client.write_registers(write_adder, write_value, unit=unit)
                    ModbusClient._need_write = False
                    print(f"write info :{write_info}")
            except Exception as e:
                print(f"read error :{e}")
            time.sleep(sleep_time)

    def need_write_info(self, write_adder, write_value, unit=1):
        """

        :param write_adder: 写入地址
        :param write_value: 写入数据
        :param unit:
        :return:
        """
        ModbusClient._need_write_info["write_adder"] = write_adder
        ModbusClient._need_write_info["write_value"] = write_value
        ModbusClient._need_write_info["unit"] = unit
        ModbusClient._need_write = True

    def keep_need_write_info(self, write_info):
        """
        持续写入
        :return:
        """
        i = 0
        write_adder = write_info.get("write_adder", 0)
        sleep_time = write_info.get("sleep_time", 1)
        while True:
            i += 1
            self.need_write_info(write_adder, i)
            time.sleep(sleep_time)

    def start_multi_process(self, read_adder, read_length, write_adder, write_value, **kwargs):
        """
        开始多进程读写
        """
        if kwargs.get("single_connection", True):
            self.connect()

        keep_read_process = Process(target=self.__keep_read, args=(read_adder, read_length), kwargs=kwargs)
        # daemon=True)
        keep_read_process.start()
        keep_write_process = Process(target=self.__keep_write, args=(write_adder, write_value), kwargs=kwargs)
        # daemon=True)
        keep_write_process.start()

    def start_multi_thread(self, read_adder, read_length, write_adder, write_value, **kwargs):
        """
        开始线程 读写
        """
        if kwargs.get("single_connection", True):
            self.connect()

        keep_read_thread = Thread(target=self.__keep_read, args=(read_adder, read_length), kwargs=kwargs)
        keep_read_thread.start()
        keep_write_thread = Thread(target=self.__keep_write, args=(write_adder, write_value), kwargs=kwargs)
        keep_write_thread.start()

    def start_single_thread(self, read_info: dict, write_info: dict):
        """
        单线程循环读写
        """
        self.connect()
        cyclic_read_write_thread = Thread(target=self.cyclic_read_write, args=(read_info, write_info))
        cyclic_read_write_thread.start()
        keep_write_thread = Thread(target=self.keep_need_write_info, args=(write_info, write_info))
        keep_write_thread.start()


if __name__ == '__main__':
    modbus_cline = ModbusClient("192.168.20.128", 5020)
    # modbus_cline.start_multi_process(0, 10, 20, 20, single_connection=False, sleep_time=0)
    # modbus_cline.start_multi_process(0, 10, 20, 20, single_connection=True)
    # modbus_cline.start_multi_thread(0, 10, 20, 20, single_connection=False)
    # modbus_cline.start_multi_thread(0, 10, 20, 20, single_connection=True)

    read_info = {"read_adder": 0,
                 "read_length": 10,
                 "unit": 1,
                 "sleep_time": 0.01}
    write_info = {"write_adder": 2,
                  "write_value": 10}
    modbus_cline.start_single_thread(read_info, write_info)

#
